package work.linruchang.util.bean.wrapper;


import work.linruchang.util.bean.wrapper.db.TableInfo;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 *
 * @param <FirstTable>
 * @param <SecondTable>
 */
public interface BaseWrapper<FirstTable, SecondTable> {

    //=================属性获取============================

    boolean isCountFlag();

    Class<FirstTable> getFirstTableClazz();

    Class<SecondTable> getSecondTableClazz();

    StringBuilder getSqlSB();

    List<String> getWhereSqlFragments();

    List<Object> getWhereSqlParams();

    List<Class> getWhereSqlParamsTypes();

    List<String> getJoinSqlFragments();

    List<Object> getJoinOnSqlParams();

    List<Class> getJoinOnSqlParamsTypes();

    Set<String> getGroupByFieldSqlFragments();

    Set<String> getOrderBySqlFragments();

    Long getLimitStartIndex();

    Long getLimitPageSize();

    Long getPageNum();

    Long getPageSize();

    List<String> getHavingWhereSqlFragments();

    List<Object> getHavingWhereSqlParams();

    List<Class> getHavingWhereSqlParamsTypes();

    Map<Class, TableInfo> getAllTableMap();


    //=============================================

    /**
     * 后置处理SQL
     */
    void postSQLDeal();

    /**
     * 获取主表信息
     * @return
     */
    TableInfo getMasterTableInfo();

    int joinSqlFragmentsIndexOf(String joinFragment, Class joinTable);

    /**
     * 增加连表 == 不会重复添加，都设置为非主表
     *
     * @param clazzs
     * @return
     */
    Map<Class, TableInfo> addTables(Class... clazzs);

    /**
     * 增加表 == 不会重复添加
     *
     * @param clazz 表
     * @param masterTableFlag 表{clazz}是否是主表
     * @return
     */
    Map<Class, TableInfo> addTable(Class clazz, boolean masterTableFlag);

    /**
     * 增加表 == 不会重复添加
     *
     * @param tableInfo 表信息
     * @return
     */
    Map<Class, TableInfo> addTable(TableInfo tableInfo);

    /**
     * 验证{clazz}是否是主表
     *
     * @param clazz 表
     * @return
     */
    boolean isMasterTable(Class clazz);

    /**
     * 判断{tableAlias}是否是主表
     *
     * @param tableAlias 表别名 == 仅判断表别名不会用表主名去判断
     * @return
     */
    boolean isMasterTable(String tableAlias);

    /**
     * 验证{columnName}是否是主表的属性列
     * 即columnName是否在主表中存有
     *
     * @param columnName tableClazz {columnName}列所在的表
     * @param columnName 列名
     * @return
     */
    boolean isMasterTableColumn(Class tableClazz, String columnName);

    /**
     * 验证{columnName}是否不是主表的属性列
     * 即columnName是否在主表中存有
     *
     * @param columnName tableClazz {columnName}列所在的表
     * @param columnName 列名
     * @return
     */
    boolean isNotMasterTableColumn(Class tableClazz, String columnName);

    /**
     * 获取此sql的所有参数值 == 即问号所表示的值
     *
     * @return
     */
    List<Object> getSqlParams();

    /**
     * 获取此sql的所有参数值 == 即问号所表示的值
     *
     * @return
     */
    List<Class> getSqlParamsTypes();

    /**
     * 表信息获取
     *
     * @param clazz
     * @return
     */
    TableInfo getTableInfo(Class clazz);

    /**
     * 表信息获取通过表别名
     *
     * @param tableAlias 表别名
     * @return
     */
    TableInfo getTableInfo(String tableAlias);

    /**
     * 表名获取
     * <p>
     * 获取失败，抛出异常
     *
     * @param clazz
     * @return
     */
    String getTableName(Class clazz);

    /**
     * 表别名获取
     * <p>
     * 获取失败，抛出异常
     *
     * @param clazz
     * @return
     */
    String getTableAlias(Class clazz);

    /**
     * 判断是否是列字段的SQL语句
     * @param columnName
     * @return
     */
    boolean isColumnNameFlag(String columnName);

    /**
     * 表列名添加表别名后的内容
     * 格式：name => cuom_fdf.name
     * 获取失败，抛出异常
     *
     * @param clazz      表
     * @param columnName 表字段名 == 会进行字段校验
     * @return
     */
    String getColumnAddTableAlias(Class clazz, String columnName);

    /**
     * 校验{columnNames}是否在表{clazz}中存在
     *
     * @param clazz       表
     * @param columnNames 列名
     * @return
     */
    boolean checkColumnNames(Class clazz, String... columnNames);

    /**
     * 获取SQL
     * 参数由问号代替
     * <p>
     * 完整的SQL，请查看{@link BaseWrapper#getCompleteSQL()}
     *
     * @return
     */
    String getSQL();

    /**
     * （美化）获取SQL
     * 参数由问号代替
     * <p>
     * 完整的SQL，请查看{@link BaseWrapper#getCompleteSQL()}
     *
     * @return
     */
    String getFormatSQL();

    /**
     * 获取完整SQL语句（实际参数值取代问号）
     *
     * @return
     */
    String getCompleteSQL();

    /**
     * （美化）获取完整SQL语句（实际参数值取代问号）
     *
     * @return
     */
    String getCompleteFormatSQL();
}
